package cn.iocoder.yudao.module.erp.service.purchaseinorder;

import cn.iocoder.yudao.module.erp.common.InventoryTurnover;
import cn.iocoder.yudao.module.erp.dal.dataobject.deppurchase.DepPurchaseDO;
import cn.iocoder.yudao.module.erp.dal.dataobject.priaccount.PriAccountDO;
import cn.iocoder.yudao.module.erp.dal.dataobject.pristock.PriStockDO;
import cn.iocoder.yudao.module.erp.dal.dataobject.purpurchaseorder.PurPurchaseOrderDO;
import cn.iocoder.yudao.module.erp.dal.dataobject.purpurchaseorderitem.PurPurchaseOrderItemDO;
import cn.iocoder.yudao.module.erp.dal.dataobject.suppliersendorder.SupplierSendOrderDO;
import cn.iocoder.yudao.module.erp.dal.dataobject.suppliersendorderitem.SupplierSendOrderItemDO;
import cn.iocoder.yudao.module.erp.dal.dataobject.warehouseinlist.WarehouseInListDO;
import cn.iocoder.yudao.module.erp.dal.mysql.deppurchase.DepPurchaseMapper;
import cn.iocoder.yudao.module.erp.dal.mysql.priaccount.PriAccountMapper;
import cn.iocoder.yudao.module.erp.dal.mysql.pristock.PriStockMapper;
import cn.iocoder.yudao.module.erp.dal.mysql.purpurchaseorder.PurPurchaseOrderMapper;
import cn.iocoder.yudao.module.erp.dal.mysql.purpurchaseorderitem.PurPurchaseOrderItemMapper;
import cn.iocoder.yudao.module.erp.dal.mysql.suppliersendorder.SupplierSendOrderMapper;
import cn.iocoder.yudao.module.erp.dal.mysql.suppliersendorderitem.SupplierSendOrderItemMapper;
import cn.iocoder.yudao.module.erp.dal.redis.no.ErpNoRedisDAO;
import cn.iocoder.yudao.module.system.dal.dataobject.user.AdminUserDO;
import cn.iocoder.yudao.module.system.dal.mysql.user.AdminUserMapper;
import cn.iocoder.yudao.module.system.service.notify.NotifySendService;
import cn.iocoder.yudao.module.system.service.user.AdminUserService;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import org.springframework.stereotype.Service;
import jakarta.annotation.Resource;
import org.springframework.validation.annotation.Validated;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;

import cn.iocoder.yudao.module.erp.controller.admin.purchaseinorder.vo.*;
import cn.iocoder.yudao.module.erp.dal.dataobject.purchaseinorder.PurchaseInOrderDO;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;

import cn.iocoder.yudao.module.erp.dal.mysql.purchaseinorder.PurchaseInOrderMapper;

import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.module.erp.enums.ErrorCodeConstants.*;

/**
 * ERP采购入库审批单 Service 实现类
 *
 * @author TQY
 */
@Service
@Validated
public class PurchaseInOrderServiceImpl implements PurchaseInOrderService {

    @Resource
    private PurchaseInOrderMapper purchaseInOrderMapper;
    @Resource
    private PriStockMapper priStockMapper;
    @Resource
    private PriAccountMapper priAccountMapper;
    @Resource
    private PurPurchaseOrderMapper purPurchaseOrderMapper;
    @Resource
    private DepPurchaseMapper depPurchaseMapper;
    @Resource
    private PurPurchaseOrderItemMapper purPurchaseOrderItemMapper;
    @Resource
    private SupplierSendOrderMapper supplierSendOrderMapper;
    @Resource
    private SupplierSendOrderItemMapper supplierSendOrderItemMapper;
    @Resource
    private InventoryTurnover inventoryTurnover;
    @Resource
    private ErpNoRedisDAO noRedisDAO;
    @Resource
    private NotifySendService notifySendService;
    @Resource
    private AdminUserMapper adminUserMapper;

    @Override
    public String createPurchaseInOrder(PurchaseInOrderSaveReqVO createReqVO) {
        // 插入
        PurchaseInOrderDO purchaseInOrder = BeanUtils.toBean(createReqVO, PurchaseInOrderDO.class);
        purchaseInOrderMapper.insert(purchaseInOrder);
        // 返回
        return purchaseInOrder.getId();
    }

    @Override
    public void updatePurchaseInOrder(PurchaseInOrderSaveReqVO updateReqVO) {
        // 校验存在
        validatePurchaseInOrderExists(updateReqVO.getId());
        // 更新
        PurchaseInOrderDO updateObj = BeanUtils.toBean(updateReqVO, PurchaseInOrderDO.class);
        purchaseInOrderMapper.updateById(updateObj);
    }

    @Override
    public void deletePurchaseInOrder(String id) {
        // 校验存在
        validatePurchaseInOrderExists(id);
        // 删除
        purchaseInOrderMapper.deleteById(id);
    }

    private void validatePurchaseInOrderExists(String id) {
        if (purchaseInOrderMapper.selectById(id) == null) {
            throw exception(PURCHASE_IN_ORDER_NOT_EXISTS);
        }
    }

    @Override
    public PurchaseInOrderSupplierSaveReqVO getPurchaseInOrder(String id) {
        PurchaseInOrderDO purchaseInOrderDO = purchaseInOrderMapper.selectById(id);
        PurchaseInOrderSupplierSaveReqVO purchaseInOrderSaveReqVO = BeanUtils.toBean(purchaseInOrderDO, PurchaseInOrderSupplierSaveReqVO.class);
        String outOrderId = purchaseInOrderDO.getOutOrderId();
        // 获取供应商发货单随货同行单详情
        List<SupplierSendOrderItemDO> supplierSendOrderItemDOS = supplierSendOrderItemMapper.selectListByOutOrderId(outOrderId);
        purchaseInOrderSaveReqVO.setSupplierSendOrderItems(supplierSendOrderItemDOS);
        return purchaseInOrderSaveReqVO;
    }

    @Override
    public PageResult<PurchaseInOrderDO> getPurchaseInOrderPage(PurchaseInOrderPageReqVO pageReqVO) {
        return purchaseInOrderMapper.selectPage(pageReqVO);
    }

    @Override
    public void updateStatusPurchaseInOrder(PurchaseInOrderSaveReqVO updateReqVO) {
        String orderId = updateReqVO.getPurchaseOrderId();
        // 校验存在
        validatePurchaseInOrderExists(updateReqVO.getId());
        // 更新
        PurchaseInOrderDO updateObj = BeanUtils.toBean(updateReqVO, PurchaseInOrderDO.class);
        purchaseInOrderMapper.updateById(updateObj);
        // 通过
        if (updateReqVO.getStatus().equals(3)){
            // 获取供应商发货单随货同行单详情
            List<SupplierSendOrderItemDO> supplierSendOrderItemDOS = supplierSendOrderItemMapper.selectListByOutOrderId(updateReqVO.getOutOrderId());
            // 入库（一级库）
            createPriStockAndAccount(supplierSendOrderItemDOS);
            // 发送入库消息
            sendInboundMessage(supplierSendOrderItemDOS);
            // 获取采购订单项详情
            List<PurPurchaseOrderItemDO> purPurchaseOrderItemDOS = purPurchaseOrderItemMapper.selectListByPurchaseOrderId(updateReqVO.getPurchaseOrderId());
            // 判断是否需要生成采购订单从单  修改主单状态
            updatePurchaseOrder(orderId, purPurchaseOrderItemDOS, supplierSendOrderItemDOS);
        }
    }

    /**
     * 判断是否需要生成采购订单从单  修改主单状态
     * @param purPurchaseOrderItemDOS 采购订单项详情
     * @param supplierSendOrderItemDOS 供应商发货单随货同行单详情
     */
    private void updatePurchaseOrder(String orderId, List<PurPurchaseOrderItemDO> purPurchaseOrderItemDOS, List<SupplierSendOrderItemDO> supplierSendOrderItemDOS){
        // 遍历supplierSendOrderItemDOS把productId相同的产品的inCount相加形成一个新集合
        // 用于存储产品 ID 和对应的总入库数量
        Map<Long, SupplierSendOrderItemDO> productInCountMap = new HashMap<>();

        // 遍历 supplierSendOrderItemDOS 列表
        for (SupplierSendOrderItemDO item : supplierSendOrderItemDOS) {
            Long productId = item.getProductId();
            BigDecimal inCount = item.getInCount();
            // 如果 map 中已经存在该产品 ID，则将 inCount 累加到对应的总数量上
            if (productInCountMap.containsKey(productId)) {
                productInCountMap.put(productId, productInCountMap.get(productId).setInCount(productInCountMap.get(productId).getInCount().add(inCount)));
            } else {
                // 如果 map 中不存在该产品 ID，则将其添加到 map 中
                productInCountMap.put(productId, item);
            }
        }
        // 是否需要生成从单标识
        boolean needCreateCong = false;
        // 获取总入库数量
        List<SupplierSendOrderItemDO> productInCountList = productInCountMap.values().stream().collect(Collectors.toList());
        // 遍历purPurchaseOrderItemDOS和productInCountList把productId相同的产品的SupplierSendOrderItemDO中的inCount赋值给PurPurchaseOrderItemDO中的inCount
        for (PurPurchaseOrderItemDO purPurchaseOrderItemDO : purPurchaseOrderItemDOS) {
            // 判断随货同行单中是否有当前产品
            boolean foundMatch = false;
            for (SupplierSendOrderItemDO supplierSendOrderItemDO : productInCountList) {
                if (purPurchaseOrderItemDO.getProductId().equals(supplierSendOrderItemDO.getProductId())){
                    purPurchaseOrderItemDO.setCountIn(supplierSendOrderItemDO.getInCount());
                    // 判断countId和count的值是否相同
                    if (!purPurchaseOrderItemDO.getCountIn().equals(purPurchaseOrderItemDO.getCount())){
                        needCreateCong = true;
                    }
                    foundMatch = true;
                    break;
                }
            }
            if (!foundMatch){
                needCreateCong = true;
            }
        }
        // 修改主单状态
        if (needCreateCong){
            // 修改主单状态为是主单
            purPurchaseOrderMapper.updateById(new PurPurchaseOrderDO().setId(orderId).setIsMainOrder(1));
            // 更新入库数量
            purPurchaseOrderItemMapper.updateBatch(purPurchaseOrderItemDOS);
            // 生成从单
            createPurchaseOrderCong(orderId,purPurchaseOrderItemDOS);
        }else {
            PurPurchaseOrderDO purPurchaseOrderDO = purPurchaseOrderMapper.selectById(orderId);
            String mainOrderId = purPurchaseOrderDO.getMainOrderId();
            if (mainOrderId != null){
                List<PurPurchaseOrderDO> mainOrderIdList = purPurchaseOrderMapper.selectList(new QueryWrapper<PurPurchaseOrderDO>().eq("main_order_id", mainOrderId));
                // 遍历mainOrderIdList把所有的isFinished都修改为1
                for (PurPurchaseOrderDO purPurchaseOrderDO1 : mainOrderIdList) {
                    purPurchaseOrderDO1.setIsFinished(1);
                }
                mainOrderIdList.add(purPurchaseOrderMapper.selectById(mainOrderId));
                purPurchaseOrderMapper.updateBatch(mainOrderIdList);
            }else {
                purPurchaseOrderMapper.updateById(new PurPurchaseOrderDO().setId(orderId).setIsFinished(1));
            }
        }
    }

    /**
     * 发送入库消息
     * @param supplierSendOrderItemDOS
     */
    private void sendInboundMessage(List<SupplierSendOrderItemDO> supplierSendOrderItemDOS){
        // 遍历集合把productName去重之后通过“、”连接生成一个字符串
        List<String> productNameList = supplierSendOrderItemDOS.stream().map(SupplierSendOrderItemDO::getProductName).distinct().collect(Collectors.toList());
        String productName = String.join("、", productNameList);
        SupplierSendOrderDO supplierSendOrderDO = supplierSendOrderMapper.selectById(supplierSendOrderItemDOS.get(0).getOutOrderId());
        // 获取到整合单编号
        String integrateId = supplierSendOrderDO.getIntegrateId();
        List<DepPurchaseDO> depPurchaseDOs = depPurchaseMapper.selectList(new QueryWrapper<DepPurchaseDO>().eq("integrate_id", integrateId));
        // 遍历purPurchaseOrders把所有的deptId存储到一个list中
        List<String> deptIds = depPurchaseDOs.stream().map(DepPurchaseDO::getDeptId).collect(Collectors.toList());
        // 获取用户id
        List<Long> userIds = new ArrayList<>();
        adminUserMapper.selectList(new QueryWrapper<AdminUserDO>().in("dept_id", deptIds)).forEach(adminUserDO -> userIds.add(adminUserDO.getId()));
        // 查找
        // 发送入库消息
        Map<String, Object> templateParams = new HashMap<>();
        templateParams.put("name", productName);
        notifySendService.sendSingleNotifyToAdminList(userIds, "sendInboundMessage", templateParams);
    }

    /**
     * 生成订单从单
     * @param purPurchaseOrderItemDOS
     */
    private void createPurchaseOrderCong(String orderId, List<PurPurchaseOrderItemDO> purPurchaseOrderItemDOS){
        PurPurchaseOrderDO purPurchaseOrderDO = purPurchaseOrderMapper.selectById(orderId);
        // 生成订单编号CGDD+日期
        String no = noRedisDAO.generate(ErpNoRedisDAO.PURPURCHASEOEDER_ORDER_NO_PREFIX);
        if (purPurchaseOrderMapper.selectByNo(no) != null) {
            throw exception(PUR_PURCHASE_CHECK_NO_EXISTS);
        }
        String mainOrderId = purPurchaseOrderDO.getMainOrderId();
        if (mainOrderId == null){
            mainOrderId = orderId;
        }
        // 插入从单
        PurPurchaseOrderDO purPurchaseOrderDO1 = new PurPurchaseOrderDO().setPurchaseOrderId(no).setSupplierId(purPurchaseOrderDO.getSupplierId()).setDeptId(purPurchaseOrderDO.getDeptId()).setIntegrateId(purPurchaseOrderDO.getIntegrateId()).setMainOrderId(mainOrderId);
        purPurchaseOrderMapper.insert(purPurchaseOrderDO1);
        List<PurPurchaseOrderItemDO> list = new ArrayList<>();
        // 遍历purPurchaseOrderItemDOS把countIn和count不相等的项生成从单
        for (PurPurchaseOrderItemDO purPurchaseOrderItemDO : purPurchaseOrderItemDOS) {
            if (!purPurchaseOrderItemDO.getCountIn().equals(purPurchaseOrderItemDO.getCount())){
                PurPurchaseOrderItemDO purPurchaseOrderItemDO1 = new PurPurchaseOrderItemDO();
                purPurchaseOrderItemDO1.setProductId(purPurchaseOrderItemDO.getProductId()).setProductName(purPurchaseOrderItemDO.getProductName())
                        .setProductCategoryId(purPurchaseOrderItemDO.getProductCategoryId()).setProductCategoryName(purPurchaseOrderItemDO.getProductCategoryName())
                        .setProductUnitId(purPurchaseOrderItemDO.getProductUnitId()).setProductUnitName(purPurchaseOrderItemDO.getProductUnitName())
                        .setProductPrice(purPurchaseOrderItemDO.getProductPrice()).setProductStandards(purPurchaseOrderItemDO.getProductStandards())
                        .setPurchaseOrderId(purPurchaseOrderDO1.getId()).setTotalPrice(purPurchaseOrderItemDO.getProductPrice().multiply(purPurchaseOrderItemDO.getCountIn()))
                        .setCount(purPurchaseOrderItemDO.getCountIn());
                list.add(purPurchaseOrderItemDO1);
            }
        }
        // 把list中的所有totalPrice相加
        BigDecimal totalPrice = new BigDecimal(0);
        for (PurPurchaseOrderItemDO purPurchaseOrderItemDO : list) {
            totalPrice = totalPrice.add(purPurchaseOrderItemDO.getTotalPrice());
        }
        purPurchaseOrderMapper.updateById(new PurPurchaseOrderDO().setId(purPurchaseOrderDO1.getId()).setTotalPrice(totalPrice));
        purPurchaseOrderItemMapper.insert(list);
    }

    // 新增一级库入库数据和一级库台账信息
    private void createPriStockAndAccount(List<SupplierSendOrderItemDO> supplierSendOrderItemDOS){
        List<PriStockDO> erpPriStockDOS = new ArrayList<>();
        List<PriAccountDO> erpPriStockAccountDOS = new ArrayList<>();
        String inBoundBatch = createInBoundBatch();
        // 生成入库单
        WarehouseInListDO warehouseInListDO = new WarehouseInListDO();
        warehouseInListDO.setInDeptId("119");
        warehouseInListDO.setOutDeptId(null);
        String inId = inventoryTurnover.creatWarehouseInList(warehouseInListDO);
        // 遍历supplierSendOrderItemDOS只保留inCount不为0的数据
        for (SupplierSendOrderItemDO supplierSendOrderItemDO : supplierSendOrderItemDOS) {
            if (!supplierSendOrderItemDO.getInCount().equals(0)){
                PriStockDO priStockDO = new PriStockDO();
                priStockDO.setInboundBatch(inBoundBatch).setProductId(supplierSendOrderItemDO.getProductId())
                        .setProductName(supplierSendOrderItemDO.getProductName()).setProductBatch(supplierSendOrderItemDO.getBatch())
                        .setProductCategoryName(supplierSendOrderItemDO.getProductCategoryName()).setProductCategoryId(supplierSendOrderItemDO.getProductCategoryId())
                        .setProductPrice(supplierSendOrderItemDO.getProductPrice()).setProductUnitId(supplierSendOrderItemDO.getProductUnitId()).setProductUnitName(supplierSendOrderItemDO.getProductUnitName())
                        .setProductStandards(supplierSendOrderItemDO.getProductStandards()).setProductValidityDate(supplierSendOrderItemDO.getValidityDate())
                        .setDeptId(Long.valueOf("119")).setCount(supplierSendOrderItemDO.getInCount());
                erpPriStockDOS.add(priStockDO);
                erpPriStockAccountDOS.add(BeanUtils.toBean(priStockDO, PriAccountDO.class).setAffairs("采购入库").setAffairsId(inId).setMainId("采购入库"));
            }
        }
        // 批量新增一级库入库数据和一级库台账信息
        priStockMapper.insertBatch(erpPriStockDOS);
        priAccountMapper.insertBatch(erpPriStockAccountDOS);
    }

    // 生成入库批次字符串
    private String createInBoundBatch(){
        // 获取当前时间
        LocalDateTime now = LocalDateTime.now();
        // 定义日期时间格式器，格式为"yyyyMM"
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMM");
        // 格式化当前时间并返回
        return now.format(formatter);
    }

    @Override
    public void updatePurchaseInOrderReStatus(PurchaseInOrderSupplierSaveReqVO updateReqVO) {
        // 校验存在
        validatePurchaseInOrderExists(updateReqVO.getId());
        // 更新
        PurchaseInOrderDO updateObj = BeanUtils.toBean(updateReqVO, PurchaseInOrderDO.class).setStatus(1).setOpinion("");
        purchaseInOrderMapper.updateById(updateObj);
        List<SupplierSendOrderItemDO> supplierSendOrderItems = updateReqVO.getSupplierSendOrderItems();
        // 修改随货同行单入库数
        supplierSendOrderItemMapper.updateBatch(supplierSendOrderItems);
    }

}